﻿using FluentParser.Expressions;
using FluentParser.Expressions.Terminals.Parsing;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace FluentParser.Tests.Expressions.Terminals.Parsing
{
    [TestClass]
    public class ParseExactSymbolTerminalTests
    {
        [TestMethod]
        public void Parse_WhenParsingAMatchingWord_ShouldReturnTheWord()
        {
            ParseExactSymbolTerminal token = new ParseExactSymbolTerminal("MatchingWord");
            ParsingResult<object> result = token.Parse("MatchingWordAndSomethingElse");

            var expected = "MatchingWord";
            var actual = result.Value;

            Assert.AreEqual(expected, actual);
            Assert.AreEqual(expected.Length, result.Length);
        }

        [TestMethod]
        public void Parse_WhenParsingANonMatchingWord_ShouldReturnNull()
        {
            ParseExactSymbolTerminal token = new ParseExactSymbolTerminal("NonMatchingWord");

            var expected = (ParsingResult<string>)null;
            var actual = token.Parse("SomethingElse");

            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void Parse_WhenParsingAnEmptyString_ShouldAlwaysReturnAnEmptyString()
        {
            ParseExactSymbolTerminal token = new ParseExactSymbolTerminal("");
            ParsingResult<object> result = token.Parse("SomeText");

            var expected = "";
            var actual = result.Value;

            Assert.AreEqual(expected, actual);
            Assert.AreEqual(0, result.Length);
        }

        [TestMethod]
        public void ParseNode_WhenParsingAMatchingWord_ShouldReturnTheWord()
        {
            ParseExactSymbolTerminal token = new ParseExactSymbolTerminal("MatchingWord");
            ParsingNodeResult node = token.ParseNode("MatchingWordAndSomethingElse");

            string expected = "MatchingWord";
            string actual = node.Value as string;

            Assert.AreEqual(expected, actual);
            Assert.AreEqual(expected.Length, node.Length);
            Assert.AreEqual(expected.Length, node.ExploredLength);
        }

        [TestMethod]
        public void ParseNode_WhenParsingANonMatchingWord_ShouldReturnNull()
        {
            ParseExactSymbolTerminal token = new ParseExactSymbolTerminal("SomeText");
            ParsingNodeResult node = token.ParseNode("SomethingElse");

            string expected = null;
            string actual = node.Value as string;

            Assert.AreEqual(expected, actual);
            Assert.AreEqual(0, node.Length);
            Assert.AreEqual(5, node.ExploredLength);
        }

        [TestMethod]
        public void ParseNode_WhenParsingAnEmptyString_ShouldAlwaysReturnAnEmptyString()
        {
            ParseExactSymbolTerminal token = new ParseExactSymbolTerminal("");
            ParsingNodeResult node = token.ParseNode("SomeText");

            string expected = "";
            string actual = node.Value as string;

            Assert.AreEqual(expected, actual);
            Assert.AreEqual(0, node.Length);
            Assert.AreEqual(0, node.ExploredLength);
        }
    }
}
